import tkinter as tk
from tkinter import ttk


class AutocompleteEntry(ttk.Frame):
    def __init__(self, master, complete_list=None, **kwargs):
        super().__init__(master, **kwargs)

        # 初始化补全列表
        if complete_list is None:
            self.complete_list = ["assert", "and", "argspec", "func_callback",
                                  "function", "class", "def", "return"]
        else:
            self.complete_list = complete_list

        # 创建Entry组件
        self.entry = ttk.Entry(self)
        self.entry.pack(fill=tk.X)
        self.entry.bind("<KeyRelease>", self._on_keyrelease)
        self.entry.bind("<Tab>", self._on_tab)
        self.entry.bind("<Down>", self._on_down)
        self.entry.bind("<Up>", self._on_up)
        self.entry.bind("<Return>", self._on_return)

        # 创建Listbox用于显示补全建议
        self.listbox = tk.Listbox(self, height=5)
        self.listbox.bind("<Double-Button-1>", self._on_listbox_select)
        self.listbox.bind("<Return>", self._on_listbox_select)

        # 初始隐藏Listbox
        self.listbox.place_forget()

    def _on_keyrelease(self, event):
        # 获取当前输入内容
        current_text = self.entry.get()

        # 如果输入为空，隐藏Listbox
        if not current_text:
            self.listbox.place_forget()
            return

        # 获取匹配的补全建议
        matches = [item for item in self.complete_list
                   if item.lower().startswith(current_text.lower())]

        # 更新Listbox
        self.listbox.delete(0, tk.END)
        for match in matches:
            self.listbox.insert(tk.END, match)

        # 如果有匹配项，显示Listbox
        if matches:
            # 计算Listbox位置（在Entry下方）
            x = self.entry.winfo_x()
            y = self.entry.winfo_y() + self.entry.winfo_height()
            width = self.entry.winfo_width()
            print(x,y,width)
            self.listbox.place(x=x, y=y, width=width)
        else:
            self.listbox.place_forget()

    def _on_tab(self, event):
        current_text = self.entry.get()
        matches = [item for item in self.complete_list
                   if item.lower().startswith(current_text.lower())]

        if len(matches) == 1:
            self.entry.delete(0, tk.END)
            self.entry.insert(0, matches[0])
            self.listbox.place_forget()

        return "break"

    def _on_down(self, event):
        if self.listbox.winfo_ismapped():
            self.listbox.focus_set()
            self.listbox.selection_set(0)
            return "break"

    def _on_up(self, event):
        if self.listbox.winfo_ismapped():
            self.listbox.focus_set()
            self.listbox.selection_set(tk.END)
            return "break"

    def _on_return(self, event):
        if self.listbox.winfo_ismapped():
            self._on_listbox_select(event)
            return "break"

    def _on_listbox_select(self, event):
        selection = self.listbox.get(self.listbox.curselection())
        self.entry.delete(0, tk.END)
        self.entry.insert(0, selection)
        self.listbox.place_forget()
        self.entry.focus_set()


# 示例使用
if __name__ == "__main__":
    root = tk.Tk()
    root.title("浮动式自动补全示例")

    # 创建自定义的自动补全Entry
    autocomplete_entry = AutocompleteEntry(root)
    autocomplete_entry.pack(padx=10, pady=10, fill=tk.X)

    # 添加一些测试控件
    tk.Label(root, text="输入 'a' 或 'f' 查看自动补全效果", fg="gray").pack(pady=(0, 10))
    ttk.Button(root, text="测试按钮1").pack(fill=tk.X, padx=10, pady=5)
    ttk.Button(root, text="测试按钮2").pack(fill=tk.X, padx=10, pady=5)
    ttk.Button(root, text="测试按钮3").pack(fill=tk.X, padx=10, pady=5)

    root.mainloop()